export enum Direction {
    UP,
    DOWN,
    LEFT,
    RIGHT
}

export class Point {
    x: number;
    y: number;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
}


export class GameClass {
    private map: number[][] = Array(4).fill(0).map(() => Array(4).fill(0));
    private readonly bgColorList = ['#EEEADA59', '#EEE4DA', '#EDE0C8', '#F2B179', '#F59563', '#F67C5F',
        '#F65E3B', '#EDCF72', '#EDCC61', '#EDC850', '#EDC53F', '#EDC22E']
    private readonly colorList = ['#776E65', '#776E65'].concat(Array.from({length: 9}).fill('#F9F6F2') as string[])
    private ref: HTMLElement;
    // 获取每个span标签的数组
    private spanList: HTMLSpanElement[][] = Array(4).fill(0).map(() => Array(4).fill(0));
    private listener: (e: KeyboardEvent) => void;

    constructor(ref: HTMLElement) {
        this.ref = ref;
        for (let i = 0; i < 4; i++)
            for (let j = 0; j < 4; j++)
                this.spanList[i][j] = this.ref.children[i].children[j].children[0] as HTMLSpanElement;
        this.generatePosition()
        this.generatePosition()
        console.log(this.map)
    }

    public keydownListener(e: KeyboardEvent) {
        console.log(e.key)
        if (e.key === 'ArrowUp' || e.key === 'W' || e.key === 'w')
            this.move(Direction.UP);
        else if (e.key === 'ArrowDown' || e.key === 'S' || e.key === 's')
            this.move(Direction.DOWN);
        else if (e.key === 'ArrowLeft' || e.key === 'A' || e.key === 'a')
            this.move(Direction.LEFT);
        else if (e.key === 'ArrowRight' || e.key === 'D' || e.key === 'd')
            this.move(Direction.RIGHT);
    }

    // 开始游戏
    start(): void {
        // 监听键盘事件
        this.listener = this.keydownListener.bind(this);
        addEventListener('keyup', this.listener);
    }

    move(direction: Direction): void {
        this.ref.style.transition = 'transform 0.2s ease-out';
        this.ref.style.transform = 'translateY(-10px)';
        // 移动
        if (direction === Direction.UP || direction === Direction.DOWN) {
            // 取出对应的列数据
            for (let i = 0; i < 4; i++) {
                const column = this.map.map(row => row[i]);
                const {result, mergedIndices} = this.logic(column, direction);
                this.animateMovement(i, column, result, direction, mergedIndices);
                this.map.map((row, index) => row[i] = result[index]);
            }
        } else {
            for (let i = 0; i < 4; i++) {
                const column = this.map[i];
                const {result, mergedIndices} = this.logic(column, direction);
                this.animateMovement(i, column, result, direction, mergedIndices);
                this.map[i] = result;
            }
        }
        if (this.map.every(row => row.every(item => item !== 0))) {
            // 游戏结束
            alert('Game Over');
            removeEventListener('keyup', this.listener);
        }else {
            this.ref.style.transform = 'translateY(0)';
            this.generatePosition()
            this.refresh();
        }
    }

    // 添加动画方法
    private animateMovement(col: number, oldData: number[], newData: number[], direction: Direction, mergedIndices: number[]): void {
        for (let row = 0; row < 4; row++) {
            const span = this.spanList[row][col];

            if (mergedIndices.includes(row)) {
                // 合并动画
                span.style.transition = 'transform 0.2s ease-out, scale 0.2s ease-out';
                span.style.transform = 'scale(1.2)';
                setTimeout(() => {
                    span.style.transform = 'scale(1)';
                }, 200);
            } else if (oldData[row] !== newData[row]) {
                // 移动动画
                span.style.transition = 'transform 0.2s ease-out';
                span.style.transform = direction === Direction.UP ? 'translateY(-100%)' :
                    direction === Direction.DOWN ? 'translateY(100%)' :
                        direction === Direction.LEFT ? 'translateX(-100%)' :
                            'translateX(100%)';
                setTimeout(() => {
                    span.style.transform = 'translate(0, 0)';
                }, 10);
            }
        }
    }

    // 逻辑处理
    logic(data: number[], direction: Direction): { result: number[], mergedIndices: number[] } {
        if (direction === Direction.DOWN || direction === Direction.RIGHT) {
            data = data.reverse();
        }
        let result: number[] = Array(4).fill(0);
        let count = 0;
        let temp = 0;
        const mergedIndices: number[] = []; // 记录合并的索引
        for (let i = 0; i < 4; i++) {
            if (data[i] === 0) continue;
            if (data[i] !== 0 && temp === 0) {
                temp = data[i];
            } else if (data[i] !== 0 && temp === data[i]) {
                result[count] = temp * 2;
                mergedIndices.push(i); // 记录合并的索引
                temp = 0;
                count++;
            } else if (data[i] !== 0 && temp !== data[i]) {
                result[count] = temp;
                temp = data[i];
                count++;
            }
        }
        result[count] = temp;
        if (direction === Direction.DOWN || direction === Direction.RIGHT) {
            result = result.reverse();
        }
        return {result, mergedIndices};
    }

    generatePosition() {
        // 随机生成一个位置
        while (true) {
            const x = Math.floor(Math.random() * 4);
            const y = Math.floor(Math.random() * 4);
            if (this.map[x][y] === 0) {
                this.map[x][y] = 2;
                this.buildSpanList(new Point(x, y), true);
                return
            }
        }
    }

// 构建span标签的数组
    buildSpanList(point: Point, move?: boolean): void {
        const {x, y} = point;
        this.spanList[x][y].textContent = this.map[x][y].toString();
        const index = this.map[x][y].toString(2).length

        // 设置颜色和字体大小
        this.spanList[x][y].parentElement.style.backgroundColor = this.bgColorList[index - 1];
        this.spanList[x][y].style.color = this.colorList[index - 2];
        this.spanList[x][y].style.fontSize = index > 7 ? '45px' : '55px';
        if (move) {
            // 添加缩放动画
            this.spanList[x][y].style.transform = 'scale(0)';
            this.spanList[x][y].style.transition = 'transform 0.2s ease-out';
            // 触发动画
            setTimeout(() => {
                this.spanList[x][y].style.transform = 'scale(1)';
            }, 10);
        }
    }

// 绘制地图
    refresh(): void {
        for (let i = 0; i < 4; i++)
            for (let j = 0; j < 4; j++)
                if (this.map[i][j] === 0) {
                    this.spanList[i][j].textContent = '';
                    this.spanList[i][j].parentElement.style.backgroundColor = '#EEEADA59';
                } else {
                    this.buildSpanList(new Point(i, j))
                }

    }
}
